/*************************************************************************
	> File Name: tcp_client.c
	> Author: Maureen 
	> Mail: 1437867946@qq.com 
	> Created Time: Tue 01 Dec 2020 06:19:16 PM CST
 ************************************************************************/
#include "head.h"

int socket_connect(char *ip, int port) {
    int sockfd;
    //创建套接字:IPV4,TCP
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return -1;
    }
    //sockaddr结构体中存数据不方便
    //所以使用sockaddr_in
    struct sockaddr_in server;
    //IPV4
    server.sin_family = AF_INET;
    //转换为网络字节序
    server.sin_port = htons(port);
    //IP转换为网络地址
    server.sin_addr.s_addr = inet_addr(ip);

    if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
        return -1;
    }
    return sockfd;
}

int socket_connect_timeout(char *ip, int port, long timeout) {
    int sockfd;
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return -1;
    }
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip);
    
    make_nonblock(sockfd);//将连接设置为非阻塞的
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = timeout;
    
    fd_set wfds;
    FD_ZERO(&wfds);
    FD_SET(sockfd, &wfds);

    if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
        int retval, error;
        retval = select(sockfd + 1, NULL, &wfds, NULL, &tv);
        int len = sizeof(error);
        if (retval < 0) {
            close(sockfd);
            return -1;
        } else if (retval) {//连接成功，可写
            //没有去到socket的状态
            if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
                close(sockfd);
                return -1;
            } 
            if (error) {//真的出现了错误
                close(sockfd);
                return -1;
            }
            printf("connected!\n");
        } else {
            printf("Timeout!\n");
            close(sockfd);
            return -1;
        }
    }
    //设置为阻塞状态，以等待服务端发送的数据
    make_block(sockfd);
    return sockfd;
}


